package com.yanfan.mqtt.http;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson2.JSONObject;

import com.google.common.reflect.TypeToken;
import com.google.gson.*;
import com.yanfan.common.core.mq.DeviceReportBo;
import com.yanfan.common.enums.ServerType;
import com.yanfan.common.exception.ServiceException;
import com.yanfan.common.utils.DateUtils;
import com.yanfan.common.utils.StringUtils;
import com.yanfan.iot.domain.Device;
import com.yanfan.iot.domain.HttpParam;
import com.yanfan.iot.domain.Product;
import com.yanfan.iot.ruleEngine.MsgContext;
import com.yanfan.iot.ruleEngine.RuleProcess;
import com.yanfan.iot.service.IDeviceService;
import com.yanfan.iot.service.IProductService;
import com.yanfan.mq.redischannel.producer.MessageProducer;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 *
 */
@Slf4j
@Service
public class IotHttpClient {

    @Autowired
    private IProductService productService;

    @Resource
    private RuleProcess ruleProcess;

    @Autowired
    private IDeviceService deviceService;


    /**
     * 产品定时任务
     */
    public void ProductJob(Long productId) {
        try {
            httpRequest(productId);
        } catch (Exception e) {
            log.error("ProductJob error: {}", e.getMessage());
        }
    }

    // http请求
    public void httpRequest(Long productId) {
        //获取产品信息
        Product product = productService.selectProductByProductId(productId);
        //获取失败的标识
        List<String> code = productService.getcode();
        //获取url
        String url = product.getUrl();
        //获取请求方式
        String method = product.getMethodType();
        //获取请求参数
        List<HttpParam> paramss = JSONArray.parseArray(product.getParamsData(), HttpParam.class);
        //获取请求头
        List<HttpParam> headers = JSONArray.parseArray(product.getHeaders(), HttpParam.class);
        String data1 = null;
        //获取body数据
        String datas = JSON.parse(product.getData()).toString();
        if (product.getHttptype() == 1) {
            if (!product.getMethodType().equals("get")) {
                // 将字符串解析为JSONObject
                JSONObject jsonObject = JSONObject.parseObject(datas);
                // 添加新的字段
                jsonObject.put("token", product.getUserkey());
                // 将修改后的JSONObject转换回字符串
                data1 = jsonObject.toJSONString();
            }
        } else {
            data1 = datas;
        }

        String contentType = product.getContentType();

        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        String result = "";

        /**
         * 获取配置  发送请求  获取数据 处理数据
         */
        // 创建http请求
        HttpPost httpPost = new HttpPost(url);
        httpPost.addHeader("Content-Type", contentType);
        try {
            if ("post".equals(method)) {

                StringEntity entity = new StringEntity(data1);
                // 设置请求参数
                httpPost.setEntity(entity);
                for (int i = 0; i < headers.size(); i++) {
                    if (StringUtils.isNotEmpty(headers.get(i).getKey())) {
                        httpPost.addHeader(headers.get(i).getKey(), headers.get(i).getValue());
                    }
                }
                response = httpClient.execute(httpPost);
                int statusCode = response.getStatusLine().getStatusCode();
                if (statusCode == HttpStatus.SC_OK) {
                    result = EntityUtils.toString(response.getEntity(), "utf-8");
                    JSONObject jsonObject = JSONObject.parseObject(result);
                    String resultCode = jsonObject.getString("code");
                    System.out.println(resultCode);
                    if (code.contains(resultCode)) {
                        //获取新的key
                        String key = productService.httplogin(product.getUsername(), product.getUserpassword(), product.getHttpurl());
                        //存到数据库里面
                        productService.updatekey(key, productId);
                        //重新走定时器
                        ProductJob(productId);
                    }
                } else if (statusCode == HttpStatus.SC_UNAUTHORIZED) {
                    //获取新的key
                    String key = productService.httplogin(product.getUsername(), product.getUserpassword(), product.getHttpurl());
                    //存到数据库里面
                    productService.updatekey(key, productId);
                    //重新走定时器
                    ProductJob(productId);
                }
            } else if ("get".equals(method)) {
                // 创建http请求
                List<NameValuePair> params = new ArrayList<NameValuePair>();
                for (int i = 0; i < paramss.size(); i++) {
                    if (StringUtils.isNotEmpty(paramss.get(i).getKey())) {
                        params.add(new BasicNameValuePair(paramss.get(i).getKey(), paramss.get(i).getValue()));
                    }
                }
                URIBuilder builder = new URIBuilder(url);
                builder.setParameters(params);
                HttpGet httpGet = new HttpGet(builder.build());
                // 请求类型
                httpGet.addHeader("Content-Type", contentType);
                for (int i = 0; i < headers.size(); i++) {
                    if (StringUtils.isNotEmpty(headers.get(i).getKey())) {
                        httpGet.addHeader(headers.get(i).getKey(), headers.get(i).getValue());
                    }
                }
                if (headers.size() != 0 && product.getUserkey() != null) {
                    httpGet.addHeader("Token", product.getUserkey());
                }
                // 设置超时时间
                RequestConfig requestConfig = RequestConfig.custom()
                                                           .setConnectTimeout(3000)
                                                           .setConnectionRequestTimeout(1000)
                                                           .setSocketTimeout(3000)
                                                           .build();
                httpGet.setConfig(requestConfig);
                response = httpClient.execute(httpGet);
                int statusCode = response.getStatusLine().getStatusCode();
                //请求成功的判断
                if (statusCode == HttpStatus.SC_OK) {
                    //将响应体的内容转成utf-8编码的字符串
                    result = EntityUtils.toString(response.getEntity(), "utf-8");
                    JSONObject jsonObject = JSONObject.parseObject(result);
                    String resultCode = jsonObject.getString("code");
                    System.out.println("code=>" + resultCode);
                    if (code.contains(resultCode)) {
                        //获取新的key
                        String key = productService.httplogin(product.getUsername(), product.getUserpassword(), product.getHttpurl());
                        //存到数据库里面
                        productService.updatekey(key, productId);
                        //重新走定时器
                        ProductJob(productId);
                    }
                } else if (statusCode == HttpStatus.SC_UNAUTHORIZED) {
                    //获取新的key
                    String key = productService.httplogin(product.getUsername(), product.getUserpassword(), product.getHttpurl());
                    //存到数据库里面
                    productService.updatekey(key, productId);
                    //重新走定时器
                    ProductJob(productId);
                }
            } else if ("put".equals(method)) {
                // 创建http请求
                HttpPut httpPut = new HttpPut(url);
                httpPut.addHeader("Content-Type", contentType);
                StringEntity entity = new StringEntity(data1);
                httpPut.setEntity(entity);
                for (int i = 0; i < headers.size(); i++) {
                    if (StringUtils.isNotEmpty(headers.get(i).getKey())) {
                        httpPut.addHeader(headers.get(i).getKey(), headers.get(i).getValue());
                    }
                }
                response = httpClient.execute(httpPut);
                int statusCode = response.getStatusLine().getStatusCode();
                if (statusCode == HttpStatus.SC_OK) {
                    result = EntityUtils.toString(response.getEntity(), "utf-8");
                    JSONObject jsonObject = JSONObject.parseObject(result);
                    String resultCode = jsonObject.getString("code");
                    System.out.println(resultCode);
                    if (code.contains(resultCode)) {
                        //获取新的key
                        String key = productService.httplogin(product.getUsername(), product.getUserpassword(), product.getHttpurl());
                        //存到数据库里面
                        productService.updatekey(key, productId);
                        //重新走定时器
                        ProductJob(productId);
                    }
                } else if (statusCode == HttpStatus.SC_UNAUTHORIZED) {
                    //获取新的key
                    String key = productService.httplogin(product.getUsername(), product.getUserpassword(), product.getHttpurl());
                    //存到数据库里面
                    productService.updatekey(key, productId);
                    //重新走定时器
                    ProductJob(productId);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 关闭资源
            if (response != null) {
                try {
                    response.close();
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }
            }
            if (httpClient != null) {
                try {
                    httpClient.close();
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }
            }
        }

        System.out.println("=>获取数据：" + result);

        try {
            // 根据产品id查询设备
            List<Device> devices = deviceService.selectDeviceByProductId(productId);
            for (int i = 0; i < devices.size(); i++) {
                String serialNumber = devices.get(i).getSerialNumber();
                //   /321/D1XR2QNFD521/property/post
                String topicName = "/" + productId + "/" + serialNumber + "/property/post";
                if (!"".equals(result)) {
                    if (StringUtils.isEmpty(product.getResponseKey()) || product.getResponseKey().equals("data")) {
                        product.setResponseKey("data");
                    }
                    Gson gson = new Gson();
                    JSONObject jsonObject = new JSONObject();
                    try {
                        // 尝试将字符串解析为数组
                        Object parsed = gson.fromJson(result, Object[].class);
                        // 将字符串解析为List
                        List<Object> jsonArray = gson.fromJson(result, new TypeToken<List<Object>>() {}.getType());
                        // 如果解析成功，并且解析后的对象是数组，那么result就是一个数组
                        if (parsed instanceof Object[]) {
                            Object firstElement = jsonArray.get(0);
                            result = gson.toJson(firstElement);
                            System.out.println("result 是一个数组");
                        }
                    } catch (Exception e) {
                        // 如果解析失败，result可能不是一个有效的JSON数组
                        System.out.println("result 不是一个有效的JSON数组");
                    }
                    System.out.println(result + "数据格式");
                    jsonObject = JSONObject.parseObject(result);

                    if (!product.getResponseKey().equals("") && product.getResponseKey() != null) {
                        //通过.分割字符串获取数据响应key
                        String[] keys = product.getResponseKey().split("\\.");

                        int length = keys.length;
                        //通过循环获取数据
                        if (length == 1) {
                            if (jsonObject.containsKey(keys[0])) {
                                // 获取data键对应的值
                                Object dataObject = jsonObject.get("data");
                                // 检查data对应的值是否是JSONObject
                                if (dataObject instanceof JSONObject) {
                                    jsonObject = jsonObject.getJSONObject("data");
                                } else {
                                    // 假设 dataObject 是一个 JSONArray 对象
                                    com.alibaba.fastjson2.JSONArray dataArray = (com.alibaba.fastjson2.JSONArray) dataObject;
                                    Object firstElement = dataArray.get(0);
                                    jsonObject = com.alibaba.fastjson2.JSON.parseObject(firstElement.toString());
                                }
                            }
                        } else {
                            for (int j = 0; j < length; j++) {
                                if (jsonObject.containsKey(keys[j])) {
                                    jsonObject = jsonObject.getJSONObject(keys[j]);
                                }
                            }
                        }
                    }

                    com.alibaba.fastjson2.JSONArray dataArray = new com.alibaba.fastjson2.JSONArray();
                    for (String key : jsonObject.keySet()) {
                        JSONObject jsonObject1 = new JSONObject();
                        jsonObject1.put(key, jsonObject.get(key));
                        dataArray.add(jsonObject1);
                    }
                    //                        com.alibaba.fastjson2.JSONArray dataArray = jsonObject.getJSONArray(product.getResponseKey());
                    String data = null;
                    if (dataArray != null && !dataArray.isEmpty()) {
                        JSONArray resultArray = new JSONArray();
                        for (int i1 = 0; i1 < dataArray.size(); i1++) {
                            // 获取数组的每个元素
                            JSONObject dataObject = dataArray.getJSONObject(i1);
                            // 将每个JSONObject添加到新的JSONArray中
                            resultArray.add(dataObject);
                        }
                        // 将JSONArray转换为字符串
                        data = resultArray.toString();
                        System.out.println(data);
                    } else {
                        System.out.println("Data array is empty or null.");
                        throw new ServiceException("数据解析异常" + dataArray);
                    }
                    JsonArray array = JsonParser.parseString(data).getAsJsonArray();
                    JsonObject results = new JsonObject();

                    for (JsonElement element : array) {
                        JsonObject obj = element.getAsJsonObject();
                        for (String key : obj.keySet()) {
                            results.add(key, obj.get(key));
                        }
                    }

                    String resultString = results.toString();
                    System.out.println("解析值为resultString：" + resultString);

                    byte[] bytes = (com.alibaba.fastjson2.JSONObject.toJSONString(resultString).getBytes(StandardCharsets.UTF_8));
                    sendToMQ(serialNumber, topicName, bytes);
                }
            }
        } catch (Exception e) {
            throw new ServiceException("数据解析异常" + e.getMessage());
        }
    }

    @SneakyThrows
    public void sendToMQ(String serialNumber, String topicName, byte[] bytes) {

        /*获取topic*/
        DeviceReportBo reportBo = DeviceReportBo.builder()
                                                .serialNumber(serialNumber)
                                                .topicName(topicName)
                                                .packetId((long) 0)
                                                .platformDate(DateUtils.getNowDate())
                                                .data(bytes)
                                                .serverType(ServerType.MQTT)
                                                .build();

        /*设备上报数据*/
        reportBo.setReportType(1);
        // 规则引擎脚本处理,完成后返回结果
        MsgContext context = ruleProcess.processRuleScript(serialNumber, 1, topicName, new String(bytes));
        if (!Objects.isNull(context) && StringUtils.isNotEmpty(context.getPayload()) && StringUtils.isNotEmpty(context.getTopic())) {
            reportBo.setTopicName(context.getTopic());
            reportBo.setData(context.getPayload().getBytes(StandardCharsets.UTF_8));
        }

        MessageProducer.sendPublishMsg(reportBo);
    }
}
